#include "widget.h"
#include "ui_widget.h"
#include <QNetworkInterface>
#include <QDateTime>
#include <QScrollBar>//这个别忘了包含，在textbrowser那里用到了
Widget::Widget(QWidget *parent,QString usrname)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //绑定接收的函数
    tcpClient=new QTcpSocket(this);
    QString LocalIP=getLocalIP();
    //连接服务器
    quint16 targetport=8888;
    tcpClient->connectToHost(LocalIP,targetport);
    connect(tcpClient, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));


    uName = usrname;
    udpSocket = new QUdpSocket(this);//发送和接收的socket

    port = 10000;
    chatType=BroadCast;//默认是广播模式
    udpSocket->bind(QHostAddress::AnyIPv4,port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);//绑定端口号,这里不用绑定IP地址，和之前接触的UDP用法不一样,后面的东西能够使得新建的表内容和之前的一样, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint
    connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));//设置读取处理
    sendbroadcastmsg(UsrEnter);//广播用户登录的消息

//    connect(ui->msgTxtEdit, SIGNAL(currentCharFormatChanged(QTextCharFormat)),this, SLOT(curFmtChanged(const QTextCharFormat)));
}

Widget::~Widget()
{
    delete ui;
}

QString Widget::getLocalIP()
{
    QString hostName=QHostInfo::localHostName();
    QHostInfo hostInfo=QHostInfo::fromName(hostName);
    QString localIP="";
    QList<QHostAddress> addList=hostInfo.addresses();
    if(!addList.isEmpty())
    {
        for(int i=0;i<addList.count();i++)
        {
            QHostAddress aHost=addList.at(i);
            if(QAbstractSocket::IPv4Protocol==aHost.protocol())
            {
                localIP=aHost.toString();
                break;
            }
        }
    }
    return localIP;
}




void Widget::on_cleartoolButton_clicked()
{
 ui->msgtextBrowser->clear();
}


void Widget::on_sendpushButton_clicked()
{
    QByteArray data;
    QDataStream out(&data, QIODevice::WriteOnly);

    if(ui->target_label->text().size()==0)
    {
        QMessageBox::warning(0,tr("警告"),"请先选择聊天对象",QMessageBox::Ok);
        return;
    }
    if(ui->msgtextEdit->toPlainText().size()==0)
    {
        QMessageBox::warning(0,tr("警告"),"发送内容不能为空",QMessageBox::Ok);
        return;
    }
    if(chatType==Single)//单发模式
    {
        QString content=ui->msgtextEdit->toPlainText();
        QString time=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        QString fromname=uName;
        QString toname=ui->target_label->text().split("(").at(0);
        out<< quint8('M')<<quint8('1')<<content<<time<<fromname<<toname;//M1表示向服务器发送单聊消息
        tcpClient->write(data);//发送数据
        //清空发送的内容
        ui->msgtextEdit->clear();
        //自己这里也要显示
        ui->msgtextBrowser->setTextColor(Qt::blue);
        ui->msgtextBrowser->setCurrentFont(QFont("Times New Roman",12));
        ui->msgtextBrowser->append("[ " +fromname+"->"+toname+" ] "+ time);
        ui->msgtextBrowser->setTextColor(Qt::black);
        ui->msgtextBrowser->append(content);
        ui->msgtextBrowser->verticalScrollBar()->setValue(ui->msgtextBrowser->verticalScrollBar()->maximum());
    }
    else if(chatType==Group)//群聊模式
    {
        QString content=ui->msgtextEdit->toPlainText();
        QString time=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        QString fromname=uName;
        QString groupname=ui->target_label->text().split("(").at(0);
        out<< quint8('M')<<quint8('2')<<content<<time<<fromname<<groupname;//M2表示向服务器发送群聊消息
        tcpClient->write(data);//发送数据
        //清空发送的内容
        ui->msgtextEdit->clear();
        //这边不用显示，服务器那边会再发回来


    }



//    if(chatType==BroadCast)
//    {
//        sendbroadcastmsg(Msg);
//    }
//    else if(chatType==Group)
//    {
//        sendgroupmsg();
//    }
//    else if(chatType==Single)
//    {
//        sendmsg();
//    }
//    else
//    {
//        QMessageBox::warning(0,tr("警告"),tr("无效模式"),QMessageBox::Ok);
//    }
}


void Widget::on_exitpushButton_clicked()
{
    sendbroadcastmsg(UsrLeft);//广播离开的消息
    close();//关闭窗口
}
QString Widget::getIP()
{
    QList<QHostAddress> addrlist = QNetworkInterface::allAddresses();
    foreach (QHostAddress addr, addrlist) {
        if(addr.protocol() == QAbstractSocket::IPv4Protocol&&addr.toString().startsWith("192.168.1."))
            return addr.toString();
    }
    return 0;
}
QString Widget::getUsr()
{
    return uName;
}
void Widget::sendbroadcastmsg(MsgType type)
{
    QByteArray data;//因为信息的修改发生在接收信号的机器上，所以需要将这些信息传过去
    QDataStream out(&data, QIODevice::WriteOnly);
    QString address = getIP();
    out <<BroadCast<< type << getUsr();
    switch(type)
    {
    case Msg :
        if (ui->msgtextEdit->toPlainText() == "") {
            QMessageBox::warning(0,tr("警告"),tr("发送内容不能为空"),QMessageBox::Ok);
            return;
        }
        out << address <<ui->msgtextEdit->toHtml();
        //发送时清空编辑的内容
        ui->msgtextEdit->clear();
        ui->msgtextEdit->setFocus();
        //将显示的内容翻到最后面
        ui->msgtextBrowser->verticalScrollBar()->setValue(ui->msgtextBrowser->verticalScrollBar()->maximum());
        break;

    case UsrEnter :
        out << address;
        break;

    case UsrLeft :
        out << address;
        break;
    }
    udpSocket->writeDatagram(data,QHostAddress::Broadcast, port);
}
void Widget::sendmsg()
{
//    QByteArray data;//因为信息的修改发生在接收信号的机器上，所以需要将这些信息传过去
//    QDataStream out(&data, QIODevice::WriteOnly);
//    QString saddress = getIP();
//    QHostAddress sourceaddress(saddress);
//    if(ui->usrselectcomboBox->currentText()=="None")
//    {
//        QMessageBox::warning(0,tr("警告"),tr("请指定私聊对象"),QMessageBox::Ok);
//        return;
//    }
//    QStringList strlist=ui->usrselectcomboBox->currentText().split(",");
//    QString daddress=strlist[1];
//    QHostAddress targetaddress(daddress);
//    QString dusrname=strlist[0];

//    out <<Single<< getUsr()<<dusrname<<ui->msgtextEdit->toHtml();
//    ui->msgtextEdit->clear();
//    ui->msgtextEdit->setFocus();
//    //将显示的内容翻到最后面
//    ui->msgtextBrowser->verticalScrollBar()->setValue(ui->msgtextBrowser->verticalScrollBar()->maximum());
//    udpSocket->writeDatagram(data,data.length(),targetaddress, port);//发给对方
//    if(saddress!=daddress)udpSocket->writeDatagram(data,data.length(),sourceaddress, port);//自己也发一份，可以看到自己发的东西,同时防止选择自己时给自己发两份


}
void Widget::sendgroupmsg()
{
//    QByteArray data;//因为信息的修改发生在接收信号的机器上，所以需要将这些信息传过去
//    QDataStream out(&data, QIODevice::WriteOnly);
//    QString saddress = getIP();
//    QHostAddress sourceaddress(saddress);
//    if(ui->groupselectcomboBox->currentText()=="None")
//    {
//        QMessageBox::warning(0,tr("警告"),tr("请指定group"),QMessageBox::Ok);
//        return;
//    }
//    QString groupname=ui->groupselectcomboBox->currentText();
//    out <<Group<< getUsr()<<groupname<<ui->msgtextEdit->toHtml();
//    ui->msgtextEdit->clear();
//    ui->msgtextEdit->setFocus();
//    //将显示的内容翻到最后面
//    ui->msgtextBrowser->verticalScrollBar()->setValue(ui->msgtextBrowser->verticalScrollBar()->maximum());
//    udpSocket->writeDatagram(data,data.length(),groupAddr, port);//发给group


}
void Widget::processPendingDatagrams()//处理接收到的数据
{
    QByteArray datagram;
    datagram=tcpClient->readAll();
    QDataStream in(&datagram,QIODevice::ReadOnly);
    quint8 type1,type2;
    QString info;

    in>>type1;
    //
    if(type1=='F')//收到好友简略信息
    {
         QString username,beizhu,state,sign;
        //先清空原来的内容：
        ui->friend_listWidget->clear();
        while(sign!="e")
        {
            in>>username>>beizhu>>state>>sign;
            //将接收到的数据添加到列表中
            if(sign!="e")
            ui->friend_listWidget->addItem(username+"("+beizhu+")"+state);
        }
    }
    else if(type1=='M')//聊天消息
    {

        in>>type2;
        if(type2=='1')//单聊在线消息
        {
            QString content,time,fromusername,tousername;
            in>>content>>time>>fromusername>>tousername;//接收消息
            //将消息显示在聊天框中，这样做不好，用户体验不佳，应该是主动触发对应好友的点击事件，这样也不好，需要查找，还是不做处理吧，等用户自己点击
            //算了，写都写了，那就判断一下当前是不是目标用户，是的话就在用户眼前更新，这样用户体验更好
            if(fromusername==ui->target_label->text().split("(").at(0))
            {
                ui->msgtextBrowser->setTextColor(Qt::blue);
                ui->msgtextBrowser->setCurrentFont(QFont("Times New Roman",12));
                ui->msgtextBrowser->append("[ " +fromusername+"->"+tousername+" ] "+ time);
                ui->msgtextBrowser->setTextColor(Qt::black);
                ui->msgtextBrowser->append(content);
                ui->msgtextBrowser->verticalScrollBar()->setValue(ui->msgtextBrowser->verticalScrollBar()->maximum());
            }


        }
        else if(type2=='2')//某个好友的所有聊天消息
        {
            QString content,time,fromusername,tousername,sign;
            //先清空原来的内容：
            ui->msgtextBrowser->clear();
            while(sign!="e")
            {
                in>>content>>time>>fromusername>>tousername>>sign;//接收消息
                //将接收到的数据添加到列表中
                if(sign!="e")
                {
                    ui->msgtextBrowser->setTextColor(Qt::blue);
                    ui->msgtextBrowser->setCurrentFont(QFont("Times New Roman",12));
                    ui->msgtextBrowser->append("[ " +fromusername+"->"+tousername+" ] "+ time);
                    ui->msgtextBrowser->setTextColor(Qt::black);
                    ui->msgtextBrowser->append(content);
                }

            }
             ui->msgtextBrowser->verticalScrollBar()->setValue(ui->msgtextBrowser->verticalScrollBar()->maximum());

        }
        else if(type2=='3')//群聊在线消息
        {
            QString content,time,username,groupname,nickname;
            in>>content>>time>>username>>groupname>>nickname;//接收消息
            if(groupname==ui->target_label->text())
            {
                ui->msgtextBrowser->setTextColor(Qt::blue);
                ui->msgtextBrowser->setCurrentFont(QFont("Times New Roman",12));

                ui->msgtextBrowser->append("[ " +username+"("+nickname+")] "+ time);

                ui->msgtextBrowser->setTextColor(Qt::black);
                ui->msgtextBrowser->append(content);
                ui->msgtextBrowser->verticalScrollBar()->setValue(ui->msgtextBrowser->verticalScrollBar()->maximum());
            }


        }
        else if(type2=='4')//某个群的所有聊天消息
        {
            QString content,time,username,groupname,nickname,sign;
            //先清空原来的内容：
            ui->msgtextBrowser->clear();
            while(sign!="e")
            {
                in>>content>>time>>username>>groupname>>nickname>>sign;//接收消息
                //将接收到的数据添加到列表中
                if(sign!="e")
                {
                    ui->msgtextBrowser->setTextColor(Qt::blue);
                    ui->msgtextBrowser->setCurrentFont(QFont("Times New Roman",12));

                    ui->msgtextBrowser->append("[ " +username+"("+nickname+")] "+ time);

                    ui->msgtextBrowser->setTextColor(Qt::black);
                    ui->msgtextBrowser->append(content);
                }

            }
             ui->msgtextBrowser->verticalScrollBar()->setValue(ui->msgtextBrowser->verticalScrollBar()->maximum());

        }
    }
    else if(type1=='G')//已加入的群的列表
    {
        QString groupname;
        //先清空原来的内容：
        ui->group_listWidget->clear();
        while(groupname!="e")
        {
            in>>groupname;
            //将接收到的数据添加到列表中
            if(groupname!="e")
            ui->group_listWidget->addItem(groupname);
        }
    }

}


void Widget::on_modecomboBox_currentIndexChanged(int index)
{
    switch(index)
    {
    case 0:
        chatType=BroadCast;
        ui->msgtextBrowser->append("broadcast mode");
    break;
    case 1:
        chatType=Group;
        ui->msgtextBrowser->append("group mode");
    break;
    case 2:
        chatType=Single;
        ui->msgtextBrowser->append("single mode");
    break;
    }
}
void Widget::closeEvent(QCloseEvent *e)
{
    //

    QByteArray data;
    QDataStream out(&data, QIODevice::WriteOnly);
    QString username=uName;
   //提交登录的信息
    out<< quint8('Q')<<username;
    tcpClient->write(data);//发送数据
    qDebug()<<uName<<"logout";
    QWidget::closeEvent(e);
}


void Widget::on_groupselectcomboBox_currentIndexChanged(int index)
{
    if(index==0)udpSocket->leaveMulticastGroup(groupAddr);
    else if (index==1) {
        groupAddr=QHostAddress(QString("224.0.1.0"));
        udpSocket->joinMulticastGroup(groupAddr);
    }
    else if (index==2) {
        groupAddr=QHostAddress(QString("224.0.1.1"));
        udpSocket->joinMulticastGroup(groupAddr);
    }
    else if (index==3) {
        groupAddr=QHostAddress(QString("224.0.1.2"));
        udpSocket->joinMulticastGroup(groupAddr);
    }
    else if (index==4) {
        groupAddr=QHostAddress(QString("224.0.1.3"));
        udpSocket->joinMulticastGroup(groupAddr);
    }
}

void Widget::on_addfriend_pushButton_clicked()//添加好友
{
    //显示添加好友的界面
    addfriend=new AddFriend(uName);
    addfriend->setAttribute(Qt::WA_DeleteOnClose);
    addfriend->show();

}


void Widget::on_creategroup_pushButton_clicked()//创建群聊
{
    creategroup=new Creategroup(uName);
    creategroup->setAttribute(Qt::WA_DeleteOnClose);
    creategroup->show();

}


void Widget::on_addgroup_pushButton_clicked()//加入群聊
{
    addgroup=new Addgroup(uName);
    addgroup->setAttribute(Qt::WA_DeleteOnClose);
    addgroup->show();

}


void Widget::on_editprofile_pushButton_clicked()//修改个人资料
{

}



void Widget::on_loadmoremsg_pushButton_clicked()//显示更多聊天信息
{

}


void Widget::on_friend_listWidget_itemClicked(QListWidgetItem *item)//单击好友，将聊天信息显示在聊天框中
{
    //将选择的好友的名字放到聊天框的左上角
    ui->target_label->setText(item->text());
    //发送模式更新为single
    chatType=Single;//用于告诉发送按钮，发送的是群消息还是单聊消息
    //刷新聊天信息
    QByteArray data;
    QDataStream out(&data, QIODevice::WriteOnly);
    QString fromusername=ui->target_label->text().split("(").at(0);
    QString touser=uName;
   //提交请求聊天消息
    out<< quint8('S')<<quint8('3')<<fromusername<<touser;
    tcpClient->write(data);//发送数据

}


void Widget::on_friend_listWidget_itemDoubleClicked(QListWidgetItem *item)//双击弹出好友的详细信息界面，这边可以删除好友
{

}


void Widget::on_group_listWidget_itemClicked(QListWidgetItem *item)//单击群聊列表，将群聊消息展示在聊天框中
{
    //写这东西真的是太累了
    //将选择的群聊的名字放到聊天框的左上角
    ui->target_label->setText(item->text());
    //发送模式更新为single
    chatType=Group;//用于告诉发送按钮，发送的是群消息还是单聊消息
    //刷新聊天信息
    QByteArray data;
    QDataStream out(&data, QIODevice::WriteOnly);
    QString groupname=ui->target_label->text();
   //提交请求聊天消息
    out<< quint8('S')<<quint8('6')<<groupname;//S6表示显示所有群聊的信息
    tcpClient->write(data);//发送数据


}



void Widget::on_group_listWidget_itemDoubleClicked(QListWidgetItem *item)//双击群聊列表，编辑群聊的资料，可以退出群聊
{

}


void Widget::on_refresh_pushButton_clicked()//刷新信息
{
    //申请好友信息
    QByteArray data;
    QDataStream out(&data, QIODevice::WriteOnly);
    out<< quint8('S')<<quint8('2')<<uName;//S2表示向服务器获取所有好友基础信息（昵称，原名，状态）
    tcpClient->write(data);//发送数据

    tcpClient->waitForReadyRead();
    //申请群聊列表，话说连续发两条过去会不会出问题

    QByteArray data1;
    QDataStream out1(&data1, QIODevice::WriteOnly);
    out1<< quint8('S')<<quint8('4')<<uName;//S4表示向服务器获取所有加入群聊的消息
    tcpClient->write(data1);//发送数据




    //申请聊天信息（只有在选择了聊天目标后才会有效）TODO不要了，改为点击名字主动触发

}

